Inherited Widgets Explained - Flutter Widgets 101 Ep. 3:

Youtube 地址:https://youtu.be/Zbm3hjPjQMk

InheritedWidget (Flutter Widget of the Week):

Youtube 地址:https://youtu.be/1t-8rBCGBYw


我们在编写代码时,通过 Widget 的嵌套,创建了一个 Widget Tree,当嵌套的层级变得复杂的时候,那么跨层级获取数据也就变的困难起来,你得在每一层的构造方法中添加一个属性,用于传递数据。

Flutter 自然不会允许这种情况存在,作为万物皆 Widget 的它,自然也会有一个功能性的 Widget 来处理这种情况,那就是:InheritedWidget 。

使用起来也很简单:

  1. 创建要 InheritedWidget 的子类:

    class ShareDataWidget extends InheritedWidget{
    
    }
    
  2. 按照提示重写其 updateShouldNotify 方法,顾名思义,该方法是定义“当数据发生更新时是否发出通知”,一般情况下当数据发生变化发出通知,但也有例外,例如当更新的数据和原本的数据相同,则不发出通知,所以我们一般这样写:

      @override
      bool updateShouldNotify(ShareDataWidget oldWidget) {
        return oldWidget.shareData != shareData;
      }
    
  3. 在上面的代码中的 shareData 就是我们想要共享的数据,所以我们也需要对这个数据做出定义:

    class ShareDataWidget extends InheritedWidget{
      int shareData;
      ShareDataWidget({this.shareData, Widget child}) : super(child: child);
      ...... 
    }
    
  4. 最后一步,还需要提供一个外界可以直接访问共享对象的方法:

    class ShareDataWidget extends InheritedWidget{
    
      ...... 
      static ShareDataWidget getShareData(BuildContext context) {
        return context.inheritFromWidgetOfExactType(ShareDataWidget);
      }
    }
    

至此,一个共享数据的 Widget 就创建完成了,它该如何使用?

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: new Center(
        child: ShareDataWidget(
          shareData: count,
          child: new Column(
            children: <Widget>[
              ChildWidget(),
              new MaterialButton(
                color: Colors.lightGreenAccent,
                onPressed: () {
                  count++;
                  setState(() {});
                },
                child: Text("+"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ChildWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ChildWidgetState();
  }
}

class ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    int data = ShareDataWidget.getShareData(context).shareData;
    return Text(
      "$data",
      style: TextStyle(fontSize: 50),
    );
  }
}

class ShareDataWidget extends InheritedWidget {
  final int shareData;

  ShareDataWidget({this.shareData, Widget child}) : super(child: child);

  @override
  bool updateShouldNotify(ShareDataWidget oldWidget) {
    return oldWidget.shareData != shareData;
  }

  static ShareDataWidget getShareData(BuildContext context) {
    return context.inheritFromWidgetOfExactType(ShareDataWidget);
  }
}

在上面的例子中,点击 MyApp 中的按钮,其属性 count 发生变化,同时其子控件 ChildWidget 也会收到更新通知,随着发生变化,修改 UI,同时子控件的 didChangeDependencies 回调也会被调用(代码中没有展示)。

results matching ""

    No results matching ""